const gulp = require('gulp');
const sequence = require('gulp-sequence');
const shell = require('gulp-shell');

gulp.task('clean', () => {
        const del = require('del');
        return del('./dist/');
});

gulp.task('compile-ts', shell.task('node --max-old-space-size=4000 "./node_modules/typescript/bin/tsc"'));

gulp.task('watch-ts', shell.task('tsc -w -m umd'));

gulp.task('build-html', () => {
        const through = require('through2');
        const rename = require('gulp-rename');
        const path = require('path');
        const minifyHtml = require("gulp-minify-html");
        return gulp.src('./src/**/html.ts')
                .pipe(rename((file) => {
                        const page_no = file.dirname;
                        file.basename = page_no;
                        file.extname = '.html';
                        file.dirname = '../pages';
                }))
                .pipe(through.obj((chunk, enc, callback) => {
                        const page_no = path.basename(chunk.path, '.html');
                        const head = Buffer.from(`<!DOCTYPE html>
                        <html>

                        <head>
                                <meta charset="UTF-8">
                                <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
                                <meta name="apple-mobile-web-app-capable" content="yes" />
                                <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
                                <meta name="renderer" content="webkit">
                                <link rel="stylesheet" type="text/css" href="../css/iconfont.css">
                                <link href="https://cdn.jsdelivr.net/npm/feidao-css/feidao.css" type="text/css" rel="stylesheet">
                                <link rel="stylesheet" type="text/css" href="../css/daokes.css">
                                <script src="../../node_modules/@dojo/loader/loader.js"></script>
                                <script type="text/javascript">
                                        (() => {
                                                const baseUrl = '../../node_modules/';
                                                require.config({
                                                        baseUrl: baseUrl,
                                                        packages: [{
                                                                name: 'daoke',
                                                                location: '../dist'
                                                        },{
                                                                name: '@feidao/core',
                                                                location: '@feidao/core/umd'
                                                        },{
                                                                name: '@feidao/web',
                                                                location: '@feidao/web/umd'
                                                        },{
                                                                name: '@feidao/widgets',
                                                                location: '@feidao/widgets/umd'
                                                        },{
                                                                name: '@feidao/animation',
                                                                location: '@feidao/animation/umd',
                                                                main: 'index'
                                                        },{
                                                                name: 'node-html-parser',
                                                                location: 'node-html-parser/dist/umd',
                                                                main: 'index'
                                                        },{
                                                                name: 'javascript-state-machine',
                                                                location: './javascript-state-machine',
                                                                main: 'state-machine'
                                                        },{
                                                                name: 'dask',
                                                                location: 'dask/umd',
                                                                main: 'index'
                                                        },{
                                                                name: 'mqtt',
                                                                location: './mqtt/dist',
                                                                main: 'mqtt'
                                                        },{
                                                                name: 'dot',
                                                                location: 'dot',
                                                                main: 'doT'
                                                        },{
                                                                name: 'nools-ts',
                                                                location: 'nools-ts/umd'
                                                        },{
                                                                name: 'lodash-ts',
                                                                location: 'lodash-ts/umd'
                                                        },{
                                                                name: 'he',
                                                                location: './he',
                                                                main: 'he.js'
                                                        },{
                                                                name: 'quill',
                                                                location: './quill/dist',
                                                                main: 'quill.min'
                                                        },{
                                                                name: 'i18next',
                                                                location: './i18next/dist/umd',
                                                                main: 'i18next'
                                                        },{
                                                                name: '@feidao/bscroll',
                                                                location: './@feidao/bscroll/dist',
                                                                main: "bscroll.js"
                                                        },{
                                                                name: 'jstree',
                                                                location: './jstree/dist',
                                                                main: 'jstree'
                                                        },{
                                                                name: 'jquery',
                                                                location: './jquery/dist',
                                                                main: 'jquery'
                                                        }, {
                                                                name: '@feidao/datepicker.js',
                                                                location: './@feidao/datepicker.js',
                                                                main: 'datepicker'
                                                        }, {
                                                                name: 'bootstrap-multiselect',
                                                                location: './bootstrap-multiselect',
                                                                main: 'dist/js/bootstrap-multiselect'
                                                        },{
                                                                name: 'uppy',
                                                                location: './uppy/dist',
                                                                main: 'uppy'
                                                        }, {
                                                                name: 'echarts',
                                                                location: './echarts/dist',
                                                                main: "echarts"
                                                        }, {
                                                                name: 'echarts/theme',
                                                                location: './echarts/theme/'
                                                        }]
                                                });
                                        })();
                                </script>
                        </head>
                        <body>`, 'utf8');
                        const tail = Buffer.from(`
                                <script type="text/javascript">
                                (() => {
                                        require(['daoke/${page_no}/nb'],function(main){
                                                const url = window.location.href;
                                                main.default(url).then((res) => {
                                                        document.body.innerHTML = res;
                                                        require(['daoke/${page_no}/b']);
                                                });
                                        });
                                })();
                        </script>
                        </body></html>`, 'utf8');
                        // const body = chunk.contents.toString('utf8');
                        chunk.contents = Buffer.concat([head, /*Buffer.from(body.substring(body.indexOf('`') + 1, body.lastIndexOf('`'))), */tail]);
                        // this.push(chunk);
                        // callback();
                        callback(null, chunk);
                }))
                .pipe(minifyHtml()) //压缩
                .pipe(gulp.dest('./dist/pages/'));
});

gulp.task('webpack', (cb) => {
        const dest = './dist/js/';
        const pack_file_path = `./dist/!(zj-)*/b.js`;
        const path = require('path');
        const webpack = require('webpack');
        const through = require('through');
        const ws = require('webpack-stream');
        gulp.src([pack_file_path])
                .pipe(((opts) => {
                        return through(function (file) {
                                file.named = path.basename(path.dirname(file.path));
                                this.queue(file);
                        });
                })())
                .pipe(ws({
                        mode: 'production',
                        // mode: 'development',
                        optimization: {
                                splitChunks: {
                                        name: 'feidao',
                                        chunks: 'all'
                                }
                        },
                        externals: [
                                // "nools" // this is a bad js file
                        ],
                        output: {
                                globalObject: 'window',
                                publicPath: dest
                        },
                        module: {
                                rules: [{
                                        test: /\.js$/,
                                        // exclude: /(node_modules|bower_components)/,
                                        exclude: /core-js|babel/,
                                        use: {
                                                loader: 'babel-loader'
                                        }
                                }]
                        }
                }, webpack))
                .pipe(gulp.dest(dest));
});

gulp.task('browser-sync', () => {
        const browserSync = require('browser-sync').create();
        browserSync.init({
                files: ['./dist/'],
                server: {
                        baseDir: './dist/pages/',
                        directory: true
                },
                online: false,
                serveStatic: ['./'],
                port: 8000
        });
});

gulp.task('daoke', ['watch-ts', 'build-html', 'browser-sync']);

gulp.task('nodejs', (cb) => {
        const dest = './dist/js';
        const pack_file_path = `./dist/!(zj-)*/n.js`;
        const path = require('path');
        const webpack = require('webpack');
        const through = require('through');
        const ws = require('webpack-stream');
        return (
                gulp.src([pack_file_path])
                        .pipe(((opts) => {
                                return through(function (file) {
                                        file.named = path.basename(path.dirname(file.path));
                                        this.queue(file);
                                });
                        })())
                        .pipe(ws({
                                mode: 'production',
                                module: {
                                        rules: [{
                                                test: /\.js$/,
                                                // exclude: /(node_modules|bower_components)/,
                                                exclude: /core-js|babel/,
                                                use: {
                                                        loader: 'babel-loader'
                                                }
                                        }]
                                }
                        }, webpack))
                        .pipe(gulp.dest(dest))
        );
});

gulp.task('build-service', shell.task('tsc --outDir ./dist/js/service/ -p ./service/tsconfig.json'));

gulp.task('daoke-n', sequence('clean', 'compile-ts', 'nodejs', 'build-service'));

gulp.task('default', sequence('clean', 'compile-ts', 'webpack'));


gulp.task('config', async (cb) => {
        const fs = require('fs').promises;
        const files = await fs.readdir('./src');
        const fls = files.filter((f) => {
                if (f.indexOf('zj') > -1) {
                        return f;
                }
        });
        fls.forEach((f) => {
                fs.writeFile('./src/' + f + '/config.ts', `export * from '../atom/config';\nexport const id = '${f}';`);
        });
});

gulp.task('nba2na', async (cb) => {
        const fs = require('fs').promises;
        const files = await fs.readdir('./src/')
        const fls = files.filter((f) => {
                if (f.indexOf('zj') > -1) {
                        return f;
                }
        });
        fls.forEach(async (f) => {
                const files = await fs.readdir('./src/' + f + '/');
                const fns = files.filter((f) => {
                        return /^nba/.test(f);
                });
                // nba**内容复制到na***
                const nas = await Promise.all(fns.map(async (n) => {
                        const fn = n.replace('b', '');
                        const data = await fs.readFile('./src/' + f + '/' + n, 'utf-8');
                        const d = data.replace("import nodejs from '@feidao/web/atom/nodejs/msg-b/nodejs';", "import nodejs from '@feidao/web/atom/nodejs/msg/nodejs';").replace("import get_menus from '@feidao/web/atom/nodejs/authorization-b/get-menus';", "import get_menus from '@feidao/web/atom/nodejs/authorization/get-menus';");
                        await fs.writeFile('./src/' + f + '/' + fn, d);
                        return '\'' + fn.replace('.ts', '') + '\'';
                }));
                // 修改ns文件
                await fs.writeFile('./src/' + f + '/ns.ts', `export default {\n 'fd-events-init': [${nas.join(',')}]\n};\n`);

                // 修改n文件
                const ips = nas.map((n) => {
                        return n.replace(/'/g, '');
                });;
                const ipn = ips.map((d) => {
                        return `import ${d} from './${d}';`;
                });
                const nf = `import { HTMLElement } from 'node-html-parser';
import s from './ns';

import init from '@feidao/web/framework/nodejs/d/component';
import { id, spaceid, systemid, refsystemid } from './config';

${ipn.join('\n')}

export default function main(html: HTMLElement, url: string, query: any) {
const actions = { ${ips.join(',')} };

return init(id, s, actions, html, url, query, { spaceid, systemid, refsystemid });
}`;
                await fs.writeFile('./src/' + f + '/n.ts', nf);
        });
});

gulp.task('page-n', async (cb) => {
        const fs = require('fs').promises;
        const files = await fs.readdir('./src/');

        // 选择页面文件
        const fls = files.filter((f) => {
                return !/^zj|atom/.test(f);
        });
        fls.forEach(async (f) => {
                // const f = 'function';
                // 读取页面n文件
                const filepath_nb = `./src/${f}/nb.ts`;
                const data = await fs.readFile(filepath_nb, 'utf-8');
                // 如果没有内容，不处理
                if (!data) {
                        console.error(`file [${filepath_nb}] is empty`);
                        return;
                }
                let til = '';
                let bd = '<body>';
                let check = true;
                // 获取title
                const filepath_html = `./pages/${f}.html`;
                await fs.access(filepath_html)
                        .then(async () => {
                                const page_content = await fs.readFile(filepath_html, 'utf-8');
                                if (page_content) {
                                        til = page_content.slice(page_content.indexOf('<title>') + 7, page_content.indexOf('</title>'));
                                        const bdf = page_content.slice(page_content.indexOf('<body'));
                                        bd = bdf.slice(0, bdf.indexOf('>') + 1);
                                }
                        })
                        .catch((e) => {
                                // 非菜单页面
                                check = false;
                                console.error(`There is no such file: [${f}]`);
                        });
                // 写ns.ts和na001.ts
                fs.writeFile('./src/' + f + '/ns.ts', `export default {\n       'fd-events-server-check': ['na001'],\n  "fd-events-init": []\n}`);

                if (f != 'login') {
                        // 非login页面
                        const check_page = `import { IFeidaoAiNodejsPage } from '@feidao/web/interfaces';
import check_user from '../atom-n/online-check-user';

export default async function (fd: IFeidaoAiNodejsPage, ...args: any[]) {
        return await check_user(fd);
}`;
                        const online_page = `import { IFeidaoAiNodejsPage } from '@feidao/web/interfaces';
import online_check from '../atom-n/online-check';

export default async function (fd: IFeidaoAiNodejsPage, ...args: any[]) {
        return await online_check(fd);
}`;

                        fs.writeFile('./src/' + f + '/na001.ts', check ? check_page : online_page);
                } else {
                        // login页面
                        const login_page = `import { IFeidaoAiNodejsPage } from '@feidao/web/interfaces';

export default async function (fd: IFeidaoAiNodejsPage, ...args: any[]) {
}`;
                        fs.writeFile('./src/' + f + '/na001.ts', login_page);
                }

                const actions = `import na001 from './na001';`;

                const imps = (data.match(/import\s+\w+\s+from\s+['|"]\.\.\/zj-\S+\/nb['|"];/g) || []).map((it, idx) => {
                        const no = it.replace(/import\s+\w+\s+from\s+['|"](\.\.\/zj-\S+\/n)b['|"];/, '$1');
                        return `import c${idx} from '${no}';`;
                });
                const imports = imps.join('\n');
                const params = ['html', 'url', 's', 'actions'].concat(imps.map((_, idx) => { return `c${idx}` })).join(', ');

                const constent = `import '@feidao/web/atom/nodejs/interfaces';
import html from './html';
import s from './ns';

import init from '@feidao/web/framework/nodejs/d/page';

////////////////////////////////////////////////////////////////////////////////
// import components
${imports}

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// import actions
${actions}

////////////////////////////////////////////////////////////////////////////////

feidao_exports.default = async (url: string) => {
        const actions = { na001 };

        const res = await init(${params});

        const html_str = \`<!DOCTYPE html>
<html>

        <head>
                <meta charset="UTF-8">
                <meta http-equiv="X-UA-Compatible" content="ie=edge">
                <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
                <meta name="apple-mobile-web-app-capable" content="yes" />
                <meta name="renderer" content="webkit">
                <title>${til}</title>
                <link inline rel="stylesheet" type="text/css" href="./css/iconfont.css">
                <link inline href="https://cdn.jsdelivr.net/npm/feidao-css/feidao.css" type="text/css" rel="stylesheet">
                <link inline rel="stylesheet" type="text/css" href="./css/daokes.css">
                <script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
                <script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>
                <script src="./js/feidao.js"></script>
                <script type="text/javascript">
                        window.addEventListener('WebComponentsReady', function () {
                                var t = document.createElement('script');
                                t.src = './js/${f}.js';
                                document.head.appendChild(t);
                        });
                </script>
        </head>
        ${bd}
        \${html.toString()}
        </body>
</html>
        \`;
        const html_obj = { data: html_str };
        if (typeof res === 'object' && Object.keys(res).length > 0) {
                const result = Object.assign({}, res, html_obj);
                return result;
        }
        return html_obj;
};`;
                fs.writeFile('./src/' + f + '/n.ts', constent);
        });
});